package com.mini.config;

import feign.Client;
import feign.Logger;
import feign.Request;
import feign.Response;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.cloud.netflix.feign.ribbon.CachingSpringLoadBalancerFactory;
import org.springframework.cloud.netflix.feign.ribbon.LoadBalancerFeignClient;
import org.springframework.cloud.netflix.ribbon.SpringClientFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.SSLSocketFactory;
import java.io.IOException;
import java.net.URI;

/**
 * @author anjl
 * 使用feign时，使用此配置，此配置提供功能 1、给feign请求添加oauth校验 2、在本地调用服务器端的微服务
 */
@Configuration
@EnableConfigurationProperties
@Slf4j
public class DebugFeignConfig {

    /**-----------以下配置是为了本地调试使用，测试和正式环境将${eureka.debug}设置为false即可----------**/

    @Value("${eureka.debug:false}")
    private Boolean debug;
    @Value("${eureka.debug-url:null}")
    private String debugUrl;

    public DebugFeignConfig() {
    }

    @Bean
    public Client feignClient(CachingSpringLoadBalancerFactory cachingFactory, SpringClientFactory clientFactory) {
        return new LoadFeignBalancerFeignClient(new DefaultClient(null, null), cachingFactory, clientFactory);
    }


    class LoadFeignBalancerFeignClient implements Client {
        private LoadBalancerFeignClient loadBalancerFeignClient;

        public LoadFeignBalancerFeignClient(Client delegate, CachingSpringLoadBalancerFactory lbClientFactory, SpringClientFactory clientFactory) {
            loadBalancerFeignClient = new LoadBalancerFeignClient(delegate, lbClientFactory, clientFactory);
        }

        @Override
        public Response execute(Request request, Request.Options options) throws IOException {
            URI asUri = URI.create(request.url());
            String clientName = asUri.getHost();
            DefaultClient delegate = (DefaultClient) loadBalancerFeignClient.getDelegate();
            delegate.setClientName(clientName);
            return loadBalancerFeignClient.execute(request, options);
        }
    }


    class DefaultClient extends Client.Default implements Client {
        private String clientName;

        public void setClientName(String clientName) {
            this.clientName = clientName;
        }

        public DefaultClient(SSLSocketFactory sslContextFactory, HostnameVerifier hostnameVerifier) {
            super(sslContextFactory, hostnameVerifier);
        }

        @Override
        public Response execute(Request request, Request.Options options) throws IOException {
            if(debug){
                URI asUri = URI.create(request.url());
                String url = String.format("%s/%s%s?%s", debugUrl, clientName, asUri.getPath(), asUri.getQuery());
                request = Request.create(request.method(), url, request.headers(), request.body(), request.charset());
            }
            return super.execute(request, options);
        }
    }

    @Bean
    Logger.Level feignLoggerLevel() {
        //这里记录所有，根据实际情况选择合适的日志level
        return Logger.Level.FULL;
    }
}
